Creating a nested tag structure (e.g., Coding/JavaScript) is definitely possible and adds a sophisticated layer to your blog's organization.
To achieve this, we will use a forward-slash convention in your Markdown front matter (like tags: ["Coding/JavaScript"]) and create a new filter to parse those into a tree.

1. Update your .eleventy.js

We need a new filter called groupTagsByPath. This will take your flat list of tags and turn them into a nested object. Add this inside your module.exports:

JavaScript

  eleventyConfig.addFilter("groupTagsByPath", function(allTags, collections) {  
    const tree = {};

    Object.keys(allTags).forEach(tag => {  
      // Skip the built-in 'all' and 'post' tags  
      if (tag === 'all' || tag === 'post') return;

      const parts = tag.split('/');  
      let current = tree;

      parts.forEach((part, index) => {  
        if (!current[part]) {  
          current[part] = { _posts: [], _children: {} };  
        }  
          
        // If it's the leaf node (the end of the path), add the posts  
        if (index === parts.length - 1) {  
          current[part]._posts = collections[tag] || [];  
        }  
        current = current[part]._children;  
      });  
    });

    return tree;  
  });

### ---

2. Update the Sidebar in layout.njk

Replace the "Recent Posts" section we previously discussed with this new Tag Tree. We use a recursive macro (a Nunjucks function) to handle the levels, which allows for infinite nesting (Level1 > Level2 > Level3, etc.).

HTML

<aside>  
  <section class="sidebar-section">  
    <h3>Search</h3>  
    <input type="text" id="search-input" placeholder="Search...">  
    <ul id="search-results" style="display: none;"></ul>  
  </section>

  <hr>

  <section class="sidebar-section">  
    <h3>Tags</h3>  
    <div class="archive-tree">  
      {% macro renderTag(name, data) %}  
        <details>  
          <summary>{{ name }} {% if data._posts.length > 0 %}({{ data._posts.length }}){% endif %}</summary>  
          <div style="margin-left: 15px;">  
            {# Render sub-tags if they exist #}  
            {% for childName, childData in data._children %}  
              {{ renderTag(childName, childData) }}  
            {% endfor %}

            {# Render posts at this level #}  
            <ul class="post-list">  
              {% for post in data._posts %}  
                <li><a href="{{ post.url }}">{{ post.data.title }}</a></li>  
              {% endfor %}  
            </ul>  
          </div>  
        </details>  
      {% endmacro %}

      {% set tagTree = collections | groupTagsByPath(collections) %}  
      {% for tagName, tagData in tagTree %}  
        {{ renderTag(tagName, tagData) }}  
      {% endfor %}  
    </div>  
  </section>

  <hr>

  </aside>

### ---

3. How to use it in your Posts

When you write a blog post, simply use the slash in your tags:

YAML

---
title: Learning React  
date: 2026-02-05  
tags:   
  - "Coding/Frontend/React"
  - "Personal/Journal"
---

How this works

  1. Parsing: The filter splits the tag string by /. It builds a nested JavaScript object where each level can have both its own posts and "child" tags.
  2. Recursion: The {% macro %} in Nunjucks is like a function that calls itself. If it finds a sub-category, it runs again to create another
    dropdown.
  3. UI: Because we used the same .archive-tree class, the CSS we wrote earlier (with the ▶ and ▼ arrows) will automatically apply to this tag tree as well!

4. Push to Cloudflare

Bash

git add .  
git commit -m "Add hierarchical tag tree"  
git push origin main

Since you now have a complex tag system, would you like me to show you how to display "Related Posts" at the bottom of a post based on shared tags?